package br.com.beans;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import br.com.dao.AgendaConsultaDAO;
import br.com.dao.ConvenioDAO;
import br.com.dao.ItemSaudeDAO;
import br.com.dao.MedicoDAO;
import br.com.dao.PacienteDAO;
import br.com.dao.ProntuarioDAO;
import br.com.dao.TabelaPrecosDAO;

/** Classe que representa um item de prontuario  */
@SuppressWarnings("serial")
@Entity
@Table(name="tb_prontuario")
public class Prontuario implements Serializable, Comparable<Prontuario> {

	/** Id do item */
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(nullable=false)
	private int id;

	/** Convenio */
	@ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="codigoConvenio",nullable=false)
	private Convenio convenio = new Convenio();

	/** Especialidade */
	@ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="codigoEspecialidade",nullable=false)
	private Especialidade especialidade = new Especialidade();
	
	/** Medico */
	@ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="unameMedico",nullable=false)
	private Medico medico = new Medico();
	
	/** Item de Saude */
	@ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="codigoItemSaude",nullable=false)
	private ItemSaude itemSaude = new ItemSaude();
	
	/** Quantidade do item */
	@Column(nullable=false)
	private int quantidade = 1;

	/** Data/Hora do item */
	@Temporal(value=TemporalType.TIMESTAMP)
	@Column(nullable=false)
	private Date dataHora;
	
	/** Valor (preco) do item */
	@Column(nullable=false)
	private float valor = 0.0f;

	/** Observacoes do item */
	@Column(length=50,nullable=true)
	private String observacoes;
	
	/** Paciente a que pertence este item de prontuario */
	@ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="idPaciente",nullable=false)
	private Paciente paciente = new Paciente();
	
	/** Id do item de agendamento de consulta,
	 *  para ser manipulado internamente por este bean */
	@Transient
	private int idConsulta;
	
	/** Construtor padrao */
	public Prontuario() {}

	/** Construtor de copia */
	public Prontuario(Prontuario prontuario) {
		copiar(prontuario);
	}

	/** Limpa todos atributos. */
	public void limpar() {
		setId(0);
		setConvenio(new Convenio());
		setEspecialidade(new Especialidade());
		setMedico(new Medico());
		setItemSaude(new ItemSaude());
		setQuantidade(1);
		setDataHora(null);
		setValor(0.0f);
		setObservacoes(null);
		//setPaciente(new Paciente());
	}
	
	/** Copia atributos de outro objeto.
	 *  @param obj Objeto a ser copiado */
	public void copiar(Prontuario obj) {
		if (obj != null) {
			//id = obj.id;
			convenio      = new Convenio(obj.convenio);
			especialidade = new Especialidade(obj.especialidade);
			medico        = new Medico(obj.medico);
			itemSaude     = new ItemSaude(obj.itemSaude);
			quantidade    = obj.quantidade;
			dataHora      = obj.dataHora;
			valor         = obj.valor;
			observacoes   = obj.observacoes;
			//paciente      = new Paciente(obj.paciente);
		} else {
			limpar();
		}
	}
	
	/** Remove um item de prontuario. */
	public void removerItemProntuario() {
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();
		FacesMessage facesMessage = null;

		if (prontuarioDAO.excluir(getId())) {
			facesMessage = new FacesMessage("Item removido com sucesso.",null);  
		} else {
			facesMessage = new FacesMessage("Erro ao remover item.",null);  
		}
		limpar();
		FacesContext.getCurrentInstance().addMessage(null,facesMessage);  
	}
	
	/** Adiciona uma consulta agendada ao prontuario. */
	public void adicionarConsultaProntuario() {
		ProntuarioDAO     prontuarioDAO     = new ProntuarioDAO();
		AgendaConsultaDAO agendaConsultaDAO = new AgendaConsultaDAO();
		TabelaPrecosDAO   tabelaPrecosDAO   = new TabelaPrecosDAO();
		
		FacesMessage facesMessage = null;
		
		AgendaConsulta itemAgenda = agendaConsultaDAO.localizar(idConsulta);
		
		if (itemAgenda != null) {
			setConvenio(itemAgenda.getConvenio());
			setEspecialidade(itemAgenda.getEspecialidade());
			setMedico(itemAgenda.getMedico());
			setQuantidade(1);
			setDataHora(itemAgenda.getDataHora());
			setItemSaude(itemAgenda.getItemSaude());
			setPaciente(itemAgenda.getPaciente());
		}

		float valorItem = tabelaPrecosDAO.getValor(getConvenio().getCodigo(),
				getEspecialidade().getCodigo(),
				getItemSaude().getCodigo());
		setValor(valorItem);
		
		if (prontuarioDAO.inserir(this) &&
				agendaConsultaDAO.excluir(itemAgenda.getId())){
			facesMessage = new FacesMessage("Consulta adicionada com sucesso.",null);
		} else {
			facesMessage = new FacesMessage("Erro ao adicionar consulta.",null);  
		}
		idConsulta = 0;
		limpar();
		FacesContext.getCurrentInstance().addMessage(null,facesMessage);
	}
	
	/** Adiciona um material ao prontuario. */
	public void adicionarMaterialProntuario() {
		ProntuarioDAO    prontuarioDAO    = new ProntuarioDAO();
		ConvenioDAO      convenioDAO      = new ConvenioDAO();
		MedicoDAO        medicoDAO        = new MedicoDAO();
		ItemSaudeDAO     itemSaudeDAO     = new ItemSaudeDAO();
		PacienteDAO      pacienteDAO      = new PacienteDAO();
		TabelaPrecosDAO  tabelaPrecosDAO  = new TabelaPrecosDAO();
		
		FacesMessage facesMessage = null;
		
		Convenio convenioObj = convenioDAO.localizar(getConvenio().getDescricao());
		if (convenioObj != null) setConvenio(convenioObj);
		
		Medico medicoObj = medicoDAO.localizar(getMedico().getUsuario().getUserName());
		if (medicoObj != null) setMedico(medicoObj);
		
		setEspecialidade(getMedico().getEspecialidade());

		ItemSaude itemSaudeObj = itemSaudeDAO.localizar(getItemSaude().getDescricao());
		if (itemSaudeObj != null) setItemSaude(itemSaudeObj);
		
		Paciente pacienteObj = pacienteDAO.localizar(getPaciente().getNome());
		if (pacienteObj != null) setPaciente(pacienteObj);
		
		setDataHora(new Date());
		
		float valorItem = tabelaPrecosDAO.getValor(getConvenio().getCodigo(),
				getEspecialidade().getCodigo(),
				getItemSaude().getCodigo());
		setValor(valorItem);

		if (prontuarioDAO.inserir(this)){
			facesMessage = new FacesMessage("Material/Medicamento adicionado com sucesso.",null);
		} else {
			facesMessage = new FacesMessage("Erro ao adicionar material/medicamento.",null);  
		}
		limpar();
		FacesContext.getCurrentInstance().addMessage(null,facesMessage);
	}
	
	/** Adiciona um tratamento ao prontuario. */
	public void adicionarTratamentoProntuario() {
		ProntuarioDAO    prontuarioDAO    = new ProntuarioDAO();
		ConvenioDAO      convenioDAO      = new ConvenioDAO();
		MedicoDAO        medicoDAO        = new MedicoDAO();
		ItemSaudeDAO     itemSaudeDAO     = new ItemSaudeDAO();
		PacienteDAO      pacienteDAO      = new PacienteDAO();
		TabelaPrecosDAO  tabelaPrecosDAO  = new TabelaPrecosDAO();
		
		FacesMessage facesMessage = null;
		
		Convenio convenioObj = convenioDAO.localizar(getConvenio().getDescricao());
		if (convenioObj != null) setConvenio(convenioObj);
		
		Medico medicoObj = medicoDAO.localizar(getMedico().getUsuario().getUserName());
		if (medicoObj != null) setMedico(medicoObj);
		
		setEspecialidade(getMedico().getEspecialidade());

		ItemSaude itemSaudeObj = itemSaudeDAO.localizar(getItemSaude().getDescricao());
		if (itemSaudeObj != null) setItemSaude(itemSaudeObj);
		
		Paciente pacienteObj = pacienteDAO.localizar(getPaciente().getNome());
		if (pacienteObj != null) setPaciente(pacienteObj);
		
		setDataHora(new Date());
		
		float valorItem = tabelaPrecosDAO.getValor(getConvenio().getCodigo(),
				getEspecialidade().getCodigo(),
				getItemSaude().getCodigo());
		setValor(valorItem);

		if (prontuarioDAO.inserir(this)){
			facesMessage = new FacesMessage("Tratamento/Exame adicionado com sucesso.",null);
		} else {
			facesMessage = new FacesMessage("Erro ao adicionar tratamento/exame.",null);  
		}
		limpar();
		FacesContext.getCurrentInstance().addMessage(null,facesMessage);
	}

	/** Retorna lista de consultas no prontuario.
	 *  @return Lista de consultas. */
	public List<Prontuario> getListaConsulta() {
		PacienteDAO pacienteDAO = new PacienteDAO();
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();

		Paciente pacienteObj = pacienteDAO.localizar(getPaciente().getNome());
		return prontuarioDAO.listar(pacienteObj,ItemSaude.Tipo.CONSULTA);
	}
	
	/** Retorna lista de tratamentos no prontuario.
	 *  @return Lista de tratamentos. */
	public List<Prontuario> getListaTratamento() {
		PacienteDAO pacienteDAO = new PacienteDAO();
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();

		Paciente pacienteObj = pacienteDAO.localizar(getPaciente().getNome());
		return prontuarioDAO.listar(pacienteObj,ItemSaude.Tipo.TRATAMENTO);
	}

	/** Retorna lista de materiais no prontuario.
	 *  @return Lista de materiais. */
	public List<Prontuario> getListaMaterial() {
		PacienteDAO pacienteDAO = new PacienteDAO();
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();

		Paciente pacienteObj = pacienteDAO.localizar(getPaciente().getNome());
		return prontuarioDAO.listar(pacienteObj,ItemSaude.Tipo.MATERIAL);
	}

	/** Retorna lista de consultas no prontuario, por Convenio.
	 *  @return Lista de consultas. */
	public List<Prontuario> getListaConsultaConvenio() {
		ConvenioDAO   convenioDAO   = new ConvenioDAO();
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();

		Convenio convenioObj = convenioDAO.localizar(getConvenio().getDescricao());
		return prontuarioDAO.listar(convenioObj,ItemSaude.Tipo.CONSULTA);
	}
	
	/** Retorna lista de tratamentos no prontuario, por Convenio.
	 *  @return Lista de tratamentos. */
	public List<Prontuario> getListaTratamentoConvenio() {
		ConvenioDAO   convenioDAO   = new ConvenioDAO();
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();

		Convenio convenioObj = convenioDAO.localizar(getConvenio().getDescricao());
		return prontuarioDAO.listar(convenioObj,ItemSaude.Tipo.TRATAMENTO);
	}

	/** Retorna lista de materiais no prontuario, por Convenio.
	 *  @return Lista de materiais. */
	public List<Prontuario> getListaMaterialConvenio() {
		ConvenioDAO   convenioDAO   = new ConvenioDAO();
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();

		Convenio convenioObj = convenioDAO.localizar(getConvenio().getDescricao());
		return prontuarioDAO.listar(convenioObj,ItemSaude.Tipo.MATERIAL);
	}

	/** Retorna lista de consultas no prontuario, por Medico.
	 *  @return Lista de consultas. */
	public List<Prontuario> getListaConsultaMedico() {
		MedicoDAO     medicoDAO     = new MedicoDAO();
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();

		Medico medicoObj = medicoDAO.localizarPorNome(getMedico().getUsuario().getNome());
		return prontuarioDAO.listar(medicoObj,ItemSaude.Tipo.CONSULTA);
	}
	
	/** Retorna lista de tratamentos no prontuario, por Medico.
	 *  @return Lista de tratamentos. */
	public List<Prontuario> getListaTratamentoMedico() {
		MedicoDAO     medicoDAO     = new MedicoDAO();
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();

		Medico medicoObj = medicoDAO.localizarPorNome(getMedico().getUsuario().getNome());
		return prontuarioDAO.listar(medicoObj,ItemSaude.Tipo.TRATAMENTO);
	}

	/** Retorna lista de meteriais no prontuario, por Medico.
	 *  @return Lista de materiais. */
	public List<Prontuario> getListaMaterialMedico() {
		MedicoDAO     medicoDAO     = new MedicoDAO();
		ProntuarioDAO prontuarioDAO = new ProntuarioDAO();

		Medico medicoObj = medicoDAO.localizarPorNome(getMedico().getUsuario().getNome());
		return prontuarioDAO.listar(medicoObj,ItemSaude.Tipo.MATERIAL);
	}

	public Convenio getConvenio() {
		return convenio;
	}

	public void setConvenio(Convenio convenio) {
		this.convenio = convenio;
	}

	public ItemSaude getItemSaude() {
		return itemSaude;
	}

	public void setItemSaude(ItemSaude itemSaude) {
		this.itemSaude = itemSaude;
	}

	public void setEspecialidade(Especialidade especialidade) {
		this.especialidade = especialidade;
	}

	public Especialidade getEspecialidade() {
		return especialidade;
	}

	public Medico getMedico() {
		return medico;
	}

	public void setMedico(Medico medico) {
		this.medico = medico;
	}

	public int getQuantidade() {
		return quantidade;
	}

	public void setQuantidade(int quantidade) {
		this.quantidade = quantidade;
	}

	public Date getDataHora() {
		return dataHora;
	}

	public void setDataHora(Date dataHora) {
		this.dataHora = dataHora;
	}

	public float getValor() {
		return valor;
	}

	public void setValor(float valor) {
		this.valor = valor;
	}

	public String getObservacoes() {
		return observacoes;
	}

	public void setObservacoes(String observacoes) {
		this.observacoes = observacoes;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getId() {
		return id;
	}

	public void setPaciente(Paciente paciente) {
		this.paciente = paciente;
	}

	public Paciente getPaciente() {
		return paciente;
	}

	public void setIdConsulta(int idConsulta) {
		this.idConsulta = idConsulta;
	}

	public int getIdConsulta() {
		return idConsulta;
	}

	@Override
	public int compareTo(Prontuario o) {
		if (id < o.id) return -1;
		else if (id > o.id) return 1;
		else return 0;
	}

}
